home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Libraries / VideoToolbox 97.08.16 / VideoToolboxSources / AtExitToShell.c < prev    next >
Encoding:
Text File  |  1997-07-09  |  7.4 KB  |  186 lines  |  [TEXT/CWIE]

  1. /*
  2. AtExitToShell.c
  3.  
  4.     void YourFunction(void);
  5.  
  6.     error=AtExitToShell(YourFunction);
  7.  
  8. AtExitToShell(YourFunction) requests that your function be called when the
  9. application quits, i.e. calls the ExitToShell trap, which tells the MacOS that
  10. it's done. Your function must have no arguments and no return value.
  11.  
  12. This works fine both as 68K code and as PPC code. When using the Code Fragment
  13. Manager, you could instead use the CodeWarrior Preferences panel to install your
  14. own CFM Termination routine, as suggested in the CSMP postings below, but I 
  15. haven't tried that.
  16.  
  17. (MATLAB: If you compile this file as a MEX resource, to be called from MATLAB, 
  18. then your call to AtExitToShell is a request that your function be called when 
  19. the MEX resource is flushed from memory.)
  20.  
  21. Many VideoToolbox routines set up interrupt service routines that must be killed
  22. before the program goes away. We want to kill these whether we quit via exit(),
  23. abort(), or the ExitToShell trap is invoked directly, e.g. if user types "ES"
  24. in MacsBug. The only way to be sure of killing something before the application
  25. goes away is to attach its killer, by patching, to the ExitToShell trap. That's
  26. what's done here.
  27.  
  28. AtExitToShell() is closely modeled on the ANSI function atexit(). I wrote it to
  29. overcome the restrictive implementation of atexit() and _atexit() in CodeWarrior:
  30. they only invoke your functions if the ANSI function exit() is called, NOT if
  31. you call abort(), or the user types "ES" in MacsBug. I think that AtExitToShell
  32. is equivalent to the non-ANSI _atexit() routine provided by the Symantec THINK C
  33. environment.
  34.  
  35. The registration list (of user functions) is last-in, first-out. When you
  36. eventually quit, your functions will be called in reverse of the order in which
  37. you registered them. No checking is made for duplication: the same function may
  38. be registed multiple times, and will be called multiple times.
  39.  
  40. CAUTION: your application's runtime environment (e.g. stdio) will normally have
  41. shut itself down by the time it calls ExitToShell(), so a function scheduled for 
  42. that time should not assume the availability of such services (e.g. printf). 
  43. There's no restriction on the use of MacOS services.
  44.  
  45. MATLAB: the Standard C atexit() and THINK C _atexit() routines should not be 
  46. used in MATLAB code resources, because they aren't designed to handle the
  47. situation of code that may be flushed any time MATLAB executes "clear mex" or
  48. "clear all", at a time unrelated to exiting of the MATLAB application itself. 
  49. Instead, MATLAB provides mexAtExit(), which allows you to register one callback 
  50. per MEX file, which is called when the MEX file is flushed. (The problem with using
  51. mexAtExit, is that it's hard for any particular subroutine to know whether somebody
  52. else has already used up the single available slot in the call-back table.)
  53. In order to make your C subroutines as portable and autonomous as possible, you may
  54. prefer to use this AtExitToShell() which allows you to register lots of callback 
  55. routines, and registers itself, once, with mexAtExit. 
  56.  
  57. CAUTION: Since MATLAB registers only one function per MEX it is important that 
  58. you consistently adopt one strategy. Either make lots of calls to AtExitToShell
  59. (and NONE to mexAtExit), or just one call to mexAtExit. If you call both AtExitToShell
  60. and mexAtExit then one will displace the other in MATLAB's one-entry table.
  61.  
  62. CODE FRAGMENT MANAGER:
  63.  
  64. The following is quoted from C.S.M.P. Digest, Volume 4 : Issue 31, 02 Jan 97       
  65.  
  66. >From SouthSide@kagi.com (Bob Bradley)
  67. Date: Mon, 16 Dec 1996 20:53:48 -0800
  68. Organization: SPC
  69.  
  70. In article <32B57B59.566A@kp.ssdn.skelleftea.se>,
  71. JSO0605@kp.ssdn.skelleftea.se [Johan Sˆrlin, johan.sorlin@mailbox.hogia.net] wrote:
  72.  
  73. > Can anyone please tell me how to make a PPC ExitToShell Patch?
  74. > I need a PPC function of: AtExitToShell that i found in VideoToolbox.
  75.  
  76. You can use the CFM Termination routine to do what an ExitToShell patch
  77. would do for non-CFM 68K code. Otherwise, you just need to create a
  78. RoutineDescriptor to your patched ExitToShell instead of passing just a
  79. ProcPtr to SetToolTrapAddress. [That's what the code below does--dgp]
  80.  
  81. Check out the Code Fragment Manager chapter in Inside Mac: PowerPC System
  82. Software. 
  83.  
  84. +++++++++++++++++++++++++++
  85. >From mxmora@mxmdesigns.com (Matthew Xavier Mora)
  86. Date: Mon, 16 Dec 1996 21:55:08 -0800
  87. Organization: MXM DesignsÅ
  88.  
  89. In article <32B57B59.566A@kp.ssdn.skelleftea.se>,
  90. JSO0605@kp.ssdn.skelleftea.se wrote:
  91.  
  92. > Can anyone please tell me how to make a PPC ExitToShell Patch?
  93. > I need a PPC function of: AtExitToShell that i found in VideoToolbox.
  94.  
  95.  
  96. Install a CFM Termination routine. In MW look in the Linker
  97. pref panel (I think). Type in the name of the routine that you 
  98. want called when your app exits.
  99.  
  100. Xavier
  101.  
  102. -- 
  103. Matthew Xavier Mora                    <mailto:mxmora@mxmdesigns.com>
  104.                                <http://www.best.com/~mxmora/mxm.html>
  105. +++++++++++++++++++++++++++
  106.  
  107.  
  108. HISTORY:
  109. 10/27/94 dgp wrote the ExitToShell patch, based on examples that appeared in UseNet
  110.     csmp-digest-v3-046 by Kevin Bell (kbell@cs.utexas.edu) and Bill Hofmann
  111.     (wdh@netcom.com) in response to a query by Steve Coy (stevec@jolt.mpx.com.au)
  112. 6/17/95 dgp wrote AtExitToShell.c
  113. 7/1/95 dgp made compatible with pre-universal apple headers. 
  114.     Disable if MATLAB is true. Added comments about MATLAB. 
  115. 7/17/95 dgp made compatible with pre-universal headers
  116. 4/19/96 dgp call mexAtExit(). I know this is ok for PPC, but may not work for 68k.
  117. 6/10/96 dgp fixed initialization error when MATLAB is true.
  118. 6/10/96 dgp added a couple of paragraphs explaining its use in MATLAB MEX files.
  119. 6/11/96 dgp In response to concerns raised by David Brainard, I added text above
  120.         warning about the danger of calling BOTH AtExitToShell and mexAtExit, and
  121.         I made the A5 stuff conditional on !MATLAB.
  122. 8/5/96    dgp #undef mexAtExit to make sure we call the real McCoy.
  123. 1/9/97    dgp added csmp quote about CFM, above
  124. 4/10/97    dgp    Eliminate stuff that was conditional on !UNIVERSAL_HEADERS.
  125. 7/9/97    dgp    Polished some CFM comments above.
  126. */
  127. #ifndef _VIDEOTOOLBOX_
  128.     #include "VideoToolbox.h"
  129. #endif
  130. #ifndef __TRAPS__
  131.     #include <Traps.h>    // _ExitToShell
  132. #endif
  133. #include <SegLoad.h>    // ExitToShell()
  134. typedef UniversalProcPtr TrapAddressType;
  135. static pascal void MyExitToShell(void);
  136. #define FUNCTIONS 35
  137. static UniversalProcPtr oldExitToShellTrapAddress=NULL;    // save address of real ExitToShell trap.
  138. static void (*userFunction[FUNCTIONS])(void);    // table of user functions to be called at exit.
  139.  
  140. int AtExitToShell(void (*userFunctionPtr)(void))
  141. {
  142.     #if !MATLAB
  143.         UniversalProcPtr myExitToShellUPP;
  144.     #endif
  145.     int i;
  146.     static Boolean firstTime=1;
  147.  
  148.     if(firstTime){
  149.         #if !MATLAB
  150.             myExitToShellUPP=NewRoutineDescriptor((ProcPtr)MyExitToShell
  151.                 ,kPascalStackBased,GetCurrentISA());
  152.             oldExitToShellTrapAddress=(UniversalProcPtr)GetToolTrapAddress(_ExitToShell);
  153.             SetToolTrapAddress((TrapAddressType)myExitToShellUPP,_ExitToShell);
  154.         #else
  155.             // Ask MATLAB to call MyExitToShell just before disposing of our MEX resource.
  156.             #undef mexAtExit
  157.             mexAtExit((void *)MyExitToShell);
  158.         #endif
  159.         for(i=0;i<FUNCTIONS;i++)userFunction[i]=NULL;
  160.         firstTime=0;
  161.     }
  162.     for(i=0;i<FUNCTIONS;i++)if(userFunction[i]==NULL){
  163.         userFunction[i]=userFunctionPtr;
  164.         return 0;    // success
  165.     }
  166.     return 1;        // failure: the table's already full
  167. }
  168.  
  169. static pascal void MyExitToShell(void)
  170. {
  171.     int i;
  172.     
  173.     #if !MATLAB
  174.         SetCurrentA5();
  175.         SetToolTrapAddress((TrapAddressType)oldExitToShellTrapAddress,_ExitToShell);
  176.     #endif
  177.  
  178.     for(i=FUNCTIONS-1;i>=0;i--)if(userFunction[i]!=NULL){
  179.         (*userFunction[i])();
  180.     }
  181.  
  182.     #if !MATLAB
  183.         ExitToShell();
  184.     #endif
  185. }
  186.